package com.anxin.common;

import com.anxin.exception.ForbiddenException;
import com.anxin.exception.UnauthorizedException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.nio.file.AccessDeniedException;
import java.util.List;

@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理自定义未登录异常
     */
    @ExceptionHandler(UnauthorizedException.class)
    public Result<?> handleUnauthorized(UnauthorizedException ex) {
        return Result.error(401, ex.getMessage());
    }

    /**
     * 处理无权限访问异常（@RequireRole 判断失败时抛出）
     */
    @ExceptionHandler(ForbiddenException.class)
    public Result<?> handleForbidden(ForbiddenException ex) {
        return Result.error(403, ex.getMessage());
    }

    /**
     * 处理 Spring Security 的权限拒绝异常
     */
    @ExceptionHandler(AccessDeniedException.class)
    public Result<?> handleSpringAccessDenied(AccessDeniedException ex) {
        return Result.error(403, "权限不足");
    }

    /**
     * 处理参数校验失败（JSR-303）
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        String errorMsg = fieldErrors.stream()
                .map(FieldError::getDefaultMessage)
                .findFirst()
                .orElse("参数校验失败");

        return Result.error(400, "参数错误：" + errorMsg);
    }

    /**
     * 处理单个参数校验失败
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result<?> handleConstraintViolationException(ConstraintViolationException e) {
        return Result.error(400, "参数校验失败：" + e.getMessage());
    }

    /**
     * 处理绑定异常（如@RequestParam 参数绑定失败）
     */
    @ExceptionHandler(BindException.class)
    public Result<?> handleBindException(BindException e) {
        String msg = e.getBindingResult().getFieldError().getDefaultMessage();
        return Result.error(400, "参数绑定失败：" + msg);
    }

    /**
     * 数据库唯一约束冲突异常
     */
    @ExceptionHandler(DuplicateKeyException.class)
    public Result<?> handleDuplicateKeyException(DuplicateKeyException e) {
        return Result.error(500, "数据库中已存在该记录！");
    }

    /**
     * 兜底异常处理器（系统内部错误）
     */
    @ExceptionHandler(Exception.class)
    public Result<?> handleGeneralException(Exception ex) {
        // 可以在这里记录日志或发送报警
        return Result.error(500, "系统内部错误：" + ex.getMessage());
    }
}
